﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using YJKGeometryFuncs;
using YJKRevitStairs.StairsModel.CommonUnit;
using YJKRevitStairs.StairsModel.DataInfos;

namespace YJKRevitStairs.StairsModel.Manage
{
	public class RectangleAngleStairsCreator : StairsCreator
	{
		public RectangleAngleStairsCreator(ExternalCommandData commandData) : base(commandData)
		{
		}

		private void SetMidBeamRealLacation(ref List<BeamCurveInfo> lstBeamCurve, StairsRunManager runManger, double dBeamWidth = 0.0)
		{
			double dTrans = runManger.GetStairsRunRiserThickness() + dBeamWidth;
			base.SetBeamRealLocation(ref lstBeamCurve, dTrans, BeamType.BT_Mid);
		}

		private void ChangeStairsBeamElevation(Autodesk.Revit.DB.Document doc, Stairs stairs, ref RectangleAngleStairs param_stairs)
		{
			StairsRunManager stairsRunManager = new StairsRunManager(this.m_Document, stairs);
			double baseElevation = stairs.BaseElevation;
			double stairsTreadThickness = stairsRunManager.GetStairsTreadThickness();
			ConstValueManager.GetMidBeamConstOffset();
			double stairsTreadHeight = stairsRunManager.GetStairsTreadHeight();
			if (param_stairs.m_nRunCount == 2)
			{
				double stairsRunTopElevation = stairsRunManager.GetStairsRunTopElevation(0, baseElevation);
				double stairsRunTopElevation2 = stairsRunManager.GetStairsRunTopElevation(1, baseElevation);
				double dElevation = baseElevation;
				double dElevation2 = stairsRunTopElevation - stairsTreadThickness;
				double dElevation3 = stairsRunTopElevation2 - stairsTreadThickness - stairsTreadHeight;
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Bottom, 0, dElevation);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Mid, 0, dElevation2);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Land, 0, dElevation2);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Top, 0, dElevation3);
				this.SetMidBeamRealLacation(ref param_stairs.m_listBeamCurve, stairsRunManager, 0.0);
				return;
			}
			if (param_stairs.m_nRunCount == 3)
			{
				double stairsRunTopElevation3 = stairsRunManager.GetStairsRunTopElevation(0, baseElevation);
				double stairsRunTopElevation4 = stairsRunManager.GetStairsRunTopElevation(1, baseElevation);
				double stairsRunTopElevation5 = stairsRunManager.GetStairsRunTopElevation(2, baseElevation);
				double dElevation4 = baseElevation;
				double dElevation5 = stairsRunTopElevation3 - stairsTreadThickness;
				double dElevation6 = stairsRunTopElevation4 - stairsTreadThickness;
				double dElevation7 = stairsRunTopElevation5 - stairsTreadThickness - stairsTreadHeight;
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Bottom, 0, dElevation4);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Mid, 0, dElevation5);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Land, 0, dElevation5);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Mid, 1, dElevation6);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Land, 1, dElevation6);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Top, 0, dElevation7);
				this.SetMidBeamRealLacation(ref param_stairs.m_listBeamCurve, stairsRunManager, 0.0);
				return;
			}
			if (param_stairs.m_nRunCount == 4)
			{
				double stairsRunTopElevation6 = stairsRunManager.GetStairsRunTopElevation(0, baseElevation);
				double stairsRunTopElevation7 = stairsRunManager.GetStairsRunTopElevation(1, baseElevation);
				double stairsRunTopElevation8 = stairsRunManager.GetStairsRunTopElevation(2, baseElevation);
				double stairsRunTopElevation9 = stairsRunManager.GetStairsRunTopElevation(3, baseElevation);
				double dElevation8 = baseElevation;
				double dElevation9 = stairsRunTopElevation6 - stairsTreadThickness;
				double dElevation10 = stairsRunTopElevation7 - stairsTreadThickness;
				double dElevation11 = stairsRunTopElevation8 - stairsTreadThickness;
				double dElevation12 = stairsRunTopElevation9 - stairsTreadThickness;
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Bottom, 0, dElevation8);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Mid, 0, dElevation9);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Land, 0, dElevation9);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Mid, 1, dElevation10);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Land, 1, dElevation10);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Mid, 2, dElevation11);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Land, 2, dElevation11);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Mid, 3, dElevation12);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Land, 3, dElevation12);
				base.SetBeamElevation(ref param_stairs.m_listBeamCurve, BeamType.BT_Top, 0, dElevation12);
				this.SetMidBeamRealLacation(ref param_stairs.m_listBeamCurve, stairsRunManager, 0.0);
			}
		}

		private double CalcStairTopElevation(RectangleAngleStairs param_stairs)
		{
			return param_stairs.m_dTopOffset + param_stairs.m_dLevelValue + param_stairs.m_dBottomElevation;
		}

		private ElementId EditStairs(RectangleAngleStairs param_stairs, ElementId bottomLevelId, ElementId topLevelId)
		{
			ElementId elementId = null;
			LineRunData lineRunData = param_stairs.m_listRunData[0];
			using (StairsEditScope stairsEditScope = new StairsEditScope(this.m_Document, "Stairs Automation"))
			{
				elementId = stairsEditScope.Start(bottomLevelId, topLevelId);
				Stairs stairs = this.m_Document.GetElement(elementId) as Stairs;
				using (Transaction transaction = new Transaction(this.m_Document, "Stairs Automation"))
				{
					transaction.Start();
					RunInfo runInfo = default(RunInfo);
					runInfo.RunWidth = param_stairs.m_dStairsWidth;
					runInfo.TreadDepth = lineRunData.TreadDepth;
					runInfo.TreadHeight = lineRunData.TreadHeight;
					runInfo.TreadThickness = lineRunData.TreadThickness;
					runInfo.RunStructalDepth = lineRunData.RunStructualDepth;
					runInfo.RiserThickness = lineRunData.RiserThickness;
					if (param_stairs.m_listSupport.Count > 0)
					{
						BaseSupportData baseSupportData = param_stairs.m_listSupport[0];
					}
					if (param_stairs.m_listRail.Count > 0)
					{
						BaseRaillingData baseRaillingData = param_stairs.m_listRail[0];
					}
					if (!base.ChangeStairsType(stairs, lineRunData.TheStairsType, runInfo, param_stairs.m_sName, param_stairs.m_LandingThickness))
					{
						transaction.RollBack();
						stairsEditScope.Cancel();
						return null;
					}
					try
					{
						List<double> list = new List<double>();
						double num = 0.0;
						foreach (SingleRunCurveInfo runConstructionInfo in param_stairs.m_listRunCurve)
						{
							double num2 = StairsRunCreator.CreateStairsRun(elementId, this.m_Document, num, runConstructionInfo).get_Parameter(BuiltInParameter.STAIRS_RUN_HEIGHT).AsDouble();
							num += num2;
							if (!list.Contains(num))
							{
								list.Add(num);
							}
						}
						for (int i = 0; i < param_stairs.m_listLandCurve.Count; i++)
						{
							int index = i;
							if (i > list.Count - 1)
							{
								index = list.Count - 1;
							}
							double topElevation = list[index];
							LandingCurveInfo landingCurveInfo = param_stairs.m_listLandCurve[i];
							StairsLandingCreator.CreateLanding(stairs.Id, this.m_Document, topElevation, landingCurveInfo.m_arCurveInfo);
						}
						StairsUsingRangeXdata.WriteStairsUsingRange(stairs, param_stairs.m_sUsingRange);
					}
					catch (Exception)
					{
						transaction.RollBack();
						stairsEditScope.Cancel();
						return null;
					}
					XYZ vecTrans = new XYZ(param_stairs.m_TransVector.X, param_stairs.m_TransVector.Y, 0.0);
					base.TranslationStairs(stairs, vecTrans, param_stairs.m_ptRealInsert, param_stairs.m_dBottomOffset, param_stairs.m_dTopOffset);
					stairs.DesiredRisersNumber = stairs.ActualRisersNumber;
					transaction.Commit();
					double dSupportWidth = Common.MMToFeet(50.0);
					if (param_stairs.m_listSupport.Count > 0)
					{
						dSupportWidth = base.GetSupportTypeWidth(param_stairs.m_listSupport[0].SupportType);
					}
					base.SetDefaultSurpportType(stairs, param_stairs.m_listSupport);
					List<ElementId> stairsOutsupportIds = base.GetStairsOutsupportIds(stairs, param_stairs.m_listPointsSupport, dSupportWidth);
					base.ChangeSupportType(stairs, param_stairs.m_listSupport, stairsOutsupportIds);
				}
				stairsEditScope.Commit(new StairsEditScopeFailuresPreprocessor());
			}
			return elementId;
		}

		public bool CreateRectangleAngleStairs(RectangleAngleStairs param_stairs)
		{
			bool result = true;
			ElementId elementId = null;
			ElementId elementId2 = null;
			LineRunData lineRunData = param_stairs.m_listRunData[0];
			double bottomElevation = param_stairs.m_dBottomElevation + param_stairs.m_dBottomOffset;
			double topElevation = this.CalcStairTopElevation(param_stairs);
			ElementId elementId3 = null;
			double dBottomOffset = 0.0;
			double dTopOffset = 0.0;
			if (!base.GetLevel(bottomElevation, topElevation, ref elementId, ref elementId2, ref dBottomOffset, ref dTopOffset, param_stairs.m_dTopOffset, ref elementId3) || !base.StairsLevelIsValid(elementId, elementId2))
			{
				return false;
			}
			param_stairs.m_dBottomOffset = dBottomOffset;
			param_stairs.m_dTopOffset = dTopOffset;
			ElementId elementId4 = this.EditStairs(param_stairs, elementId, elementId2);
			if (!base.IsStairsValid(elementId4))
			{
				return false;
			}
			base.ShowStairsPath(elementId4, param_stairs.m_bNoteUpStairs);
			Stairs stairs = this.m_Document.GetElement(elementId4) as Stairs;
			if (param_stairs.m_nRunCount == 4)
			{
				base.DeleteStairsTopLandRailing(stairs);
			}
			if (!base.ChangeRailingType(stairs, param_stairs.m_listRail))
			{
				return false;
			}
			using (Transaction transaction = new Transaction(this.m_Document, "Stairs Beam"))
			{
				transaction.Start();
				List<string> arLandWidth = param_stairs.m_arLandWidth;
				string sStairsLand = ElementXDataManager.m_sStairsLand;
				if (arLandWidth != null)
				{
					base.WriteStairsLandWidthXData(stairs, "StairsXData", sStairsLand, arLandWidth);
				}
				this.ChangeStairsBeamElevation(this.m_Document, stairs, ref param_stairs);
				StairsBeamCreator.CreateStairsBeam(this.m_Document, this.m_RevitVersion, param_stairs.m_BeamData, param_stairs.m_listBeamCurve, param_stairs.m_TransVector, stairs, param_stairs.m_ptRealInsert);
				ElementXDataManager.CommitStairsXData(stairs);
				transaction.Commit();
			}
			base.RotateStairs(stairs, param_stairs.m_ptRealInsert);
			base.SetStairsBottomFloorVisibility(stairs, param_stairs.m_FloorType, this.m_Document.ActiveView, base.CreateStairBottomVisibleBuiltInCate());
			double height = stairs.Height;
			if (elementId3 != null)
			{
				base.DelLevel(elementId3);
			}
			if (!YJKGeometryFuncs.Geometry.IsEqual(stairs.Height, height, 0.0001))
			{
				using (Transaction transaction2 = new Transaction(this.m_Document, "CorrectStairsHeight"))
				{
					transaction2.Start();
					stairs.Height = height;
					transaction2.Commit();
				}
			}
			return result;
		}
	}
}
